import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;

/**
 * @Author YSH
 * @Date 2024/10/11
 * @Description
 */
public class ScreenMatch {

    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    private static Integer TOTAL_SURRENDER_GAME = 1;
    private static final Integer MAX_SURRENDER_GAME = 50;

    public static void main(String[] args) throws Exception {
        repeatStartTask();
    }

    private static void repeatStartTask() {
        while (MAX_SURRENDER_GAME >= TOTAL_SURRENDER_GAME) {
            autoSurrenderTask();
            try {
                // 等待5秒再进行下一局
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        System.out.println("投降局数已达设置上限，目前总投降局数" + TOTAL_SURRENDER_GAME + "局，任务结束。。。");
    }

    private static void autoSurrenderTask() {
        try {
            Mat startScreenshot = getScreenshot();
            Robot robot = new Robot();
            // 点击“开始游戏”按钮操作
            Mat startTemplateImage = getTemplateImage(TempImageEnum.START_GAME);
            if (startTemplateImage.empty()) {
                return;
            }
            if (!getMatchResult(robot, startScreenshot, startTemplateImage)) {
                System.out.println("未进入开始游戏界面，找不到开始游戏按钮，请重新操作。");
                return;
            }
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
            Thread.sleep(3000);
            System.out.println("---进行第" + TOTAL_SURRENDER_GAME + "局游戏---");
            // 检测是否进入对局界面
            Mat gameBeginTemplateImage = getTemplateImage(TempImageEnum.GAME_BEGINS);
            System.out.println("第" + TOTAL_SURRENDER_GAME + "局游戏，匹配中。。。。。。");
            while (true) {
                Mat beginScreenshot = getScreenshot();
                if (getMatchResult(beginScreenshot, gameBeginTemplateImage)) {
                    Thread.sleep(3000);
                    System.out.println("进入对局。。。。。。");
                    break;
                }
                Thread.sleep(200);
            }

            // 已进入对局，按一次ESC键
            robot.keyPress(KeyEvent.VK_ESCAPE);
            robot.keyRelease(KeyEvent.VK_ESCAPE);
            Thread.sleep(1000);

            // 点击投降按钮
            Mat surrenderScreenshot = getScreenshot();
            Mat surrenderTemplateImage = getTemplateImage(TempImageEnum.SURRENDER);
            if (getMatchResult(robot, surrenderScreenshot, surrenderTemplateImage)) {
                robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
            }
            Thread.sleep(8000);

            // 点击胜利/失败按钮
            Mat outcomeScreenshot = getScreenshot();
            Mat defeatTemplateImage = getTemplateImage(TempImageEnum.DEFEAT);
            Boolean outcomeMatchResult = getMatchResult(robot, outcomeScreenshot, defeatTemplateImage);
            if (!outcomeMatchResult) {
                // 未匹配到说明对局胜利，点击胜利按钮
                Mat victoryTemplateImage = getTemplateImage(TempImageEnum.VICTORY);
                getMatchResult(robot, outcomeScreenshot, victoryTemplateImage);
            }
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

            // 防止对面秒投点击一次鼠标,以免卡住
            Thread.sleep(3000);
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

            // 再点击一次鼠标返回主界面
            Thread.sleep(2000);
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

            System.out.println("对局完成！目前投降局数：" + TOTAL_SURRENDER_GAME);
            // 对局计数+1
            TOTAL_SURRENDER_GAME = TOTAL_SURRENDER_GAME + 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Boolean getMatchResult(Robot robot, Mat sourceImage, Mat tempImage) throws Exception {
        // 创建结果矩阵
        Mat result = new Mat();
        // 执行模板匹配
        Imgproc.matchTemplate(sourceImage, tempImage, result, Imgproc.TM_CCOEFF_NORMED);
        // 寻找最佳匹配
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
        if (mmr.maxVal >= 0.8) {
            Point matchLoc = mmr.maxLoc;
            int x = (int) (matchLoc.x + tempImage.cols() / 2);
            int y = (int) (matchLoc.y + tempImage.rows() / 2);
            robot.mouseMove(x, y);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    private static Boolean getMatchResult(Mat sourceImage, Mat tempImage) {
        // 创建结果矩阵
        Mat result = new Mat();
        // 执行模板匹配
        Imgproc.matchTemplate(sourceImage, tempImage, result, Imgproc.TM_CCOEFF_NORMED);
        // 寻找最佳匹配
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
        return mmr.maxVal >= 0.8;
    }

    private static Mat bufferedImageToMat(BufferedImage bi) {
        BufferedImage convertedImg = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D graphics = convertedImg.createGraphics();
        graphics.drawImage(bi, 0, 0, null);
        graphics.dispose();
        byte[] pixels = ((DataBufferByte) convertedImg.getRaster().getDataBuffer()).getData();
        Mat mat = new Mat(bi.getHeight(), bi.getWidth(), CvType.CV_8UC3);
        mat.put(0, 0, pixels);
        return mat;
    }

    private static Mat getTemplateImage(TempImageEnum tempImageEnum) {
        Mat template = Imgcodecs.imread(System.getProperty("user.dir") + tempImageEnum.getPath(), Imgcodecs.IMREAD_GRAYSCALE);
        if (template.empty()) {
            System.out.println(tempImageEnum.getName() + "，模板图片加载失败");
        }
        return template;
    }

    private static Mat getScreenshot() throws Exception {
        // 获取屏幕截图
        Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
        BufferedImage capture = new Robot().createScreenCapture(screenRect);
        // 将BufferedImage转换为Mat，并确保是灰度图
        Mat img = bufferedImageToMat(capture);
        Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2GRAY);
        return img;
    }
}
